<template>
    <el-container v-loading="loading">
        <div class="container" v-if="isSuccess">
            <div class="select-container">
                <div class="select">
                    <div class="select-key">
                        <p>Select Pdb:</p>
                    </div>
                    <el-select
                        v-model="pdbValue"
                        placeholder="Select Class"
                        size="large"
                        style="width: 240px"
                        @change="handleSelectChange"
                        >
                        <el-option
                            v-for="item in pdboptions"
                            :key="item.value"
                            :label="item.label"
                            :value="item.value">
                        </el-option>
                    </el-select>
                </div>
                <div class="select" v-if="showSelectModel">
                    <div class="select-key">
                        Select Model:
                    </div>
                    <el-select
                        v-model="pdbModelValue"
                        placeholder="Select Model"
                        size="large"
                        style="width: 240px"
                        @change="handleModelSelectChange"
                        >
                        <el-option
                            v-for="item in modelOptions"
                            :key="item.value"
                            :label="item.label"
                            :value="item.value">
                        </el-option>
                    </el-select>
                </div>
            </div>
            <div id='molstar-parent' ref='molstarParent'>
                <canvas id='molstar-canvas' ref='molstarCanvas'></canvas>
            </div>
        </div>
    </el-container>
</template>

<script setup lang="ts" name="MolStar">
    import { DefaultPluginSpec, PluginSpec } from 'molstar/lib/mol-plugin/spec';
    import { PluginContext  } from 'molstar/lib/mol-plugin/context';
    import { PluginConfig } from 'molstar/lib/mol-plugin/config';
    import { onMounted, ref } from 'vue';
    import { createStructureRepresentationParams } from "molstar/lib/mol-plugin-state/helpers/structure-representation-params";
    import {
        StructureElement,
        StructureProperties,
        Structure,
    } from "molstar/lib/mol-model/structure";
    import { PluginCommands } from 'molstar/lib/mol-plugin/commands';
    import { ColorTheme } from 'molstar/lib/mol-theme/color'
    import { Script } from 'molstar/lib/mol-script/script';
    import { StructureSelection } from 'molstar/lib/mol-model/structure/query'
    import { post } from '../../../axios/api';
    import { experimentIndex } from '../dataConfigs';
    import { ElMessage } from 'element-plus'


    let pdbValue = ref('')
    let pdbModelValue = ref('')
    const props = defineProps(['gse', 'experimentType', 'sampleType'])
    const staticURL = import.meta.env.VITE_MEDIA_URL as string

    let loading = ref(false);
    let pdboptions = ref([])
    let allPaths:any = ref(null)
    let modelOptions = ref([])
    
    let isSuccess = ref(false)
    let molstarParent = ref()
    let molstarCanvas = ref()
    const showSelectModel = ref(false)

    const emit = defineEmits(['molstar-loading'])

    let plugin: PluginContext | null = null;

    const MySpec: PluginSpec = {
        ...DefaultPluginSpec(),
        layout: {
            initial: {
                showControls: true,
                isExpanded: true,
                regionState: {
                    left: 'full',
                    top: 'full',
                    right: 'full',
                    bottom: 'full',
                },
            }
        },
        config: [
            [PluginConfig.VolumeStreaming.Enabled, false],
            [PluginConfig.Viewport.ShowExpand, true],
            [PluginConfig.Viewport.ShowControls, true],
            [PluginConfig.Viewport.ShowTrajectoryControls, true],
            [PluginConfig.Viewport.ShowSettings, true],
            [PluginConfig.Viewport.ShowAnimation, true],
            [PluginConfig.Viewport.ShowTrajectoryControls, true],
            [PluginConfig.General.Transparency, 'dpoit']
        ]
    }

    function handleSelectChange(val:any) {
        if (val) {
            let list = val.split('/')
            let index = list[list.length - 1].split('_')[0]
            let keys = Object.keys(allPaths.value.folders)
            if (keys && keys.length > 0) {
                modelOptions.value = allPaths.value.folders[keys[index]].map(ele => {
                    let list = ele.split('/')
                    let label = list[list.length - 1]
                    return {label: label, value: staticURL + ele}
                })
                pdbModelValue = modelOptions.value[0]
            }
            init(val)
        }

    }

    function handleModelSelectChange(val:any) {
        if (val) {
            init(val)
        }
    }

    async function getPaths() {
        let params = {
            gse_title: props.gse,
            sample_type: props.sampleType.replaceAll(' ', '_'),
            experiment_type: experimentIndex[props.experimentType],
        }
        loading.value = true
        let res:any = await post('/get_pdb_path/', params)
        if (res && res.success) {
            loading.value = false
            isSuccess.value = true
            if (res.paths && res.paths.base_files && res.paths.base_files.length > 0) {
                allPaths.value = res.paths
                if (params.experiment_type === 'sn_m3c' && params.gse_title === 'GSE130711' && params.sample_type === 'Human_frontal_cortex') {
                    pdboptions.value = res.paths.base_files.map((ele) => {
                        let len = ele.split('/').length
                        let label = ele.split('/')[len - 1]
                        return {label: label, value: staticURL + ele}
                    })
                } else {
                    pdboptions.value = res.paths.base_files.map((ele, index) => {
                        let label = 'Leiden_' + index
                        return {label: label, value: staticURL + ele}
                    })
                }
                pdbValue.value = pdboptions.value[0].value
                let keys = Object.keys(res.paths.folders)
                if (keys && keys.length > 0) {
                    showSelectModel.value = true
                    modelOptions.value = res.paths.folders[keys[0]].map((ele, index) => {
                        let label = 'Leiden_0_Model_' + index
                        return {label: label, value: staticURL + ele}
                    })
                    pdbModelValue.value = modelOptions.value[0].value
                } else {
                    showSelectModel.value = false
                }
                init(staticURL + res.paths.base_files[0])
            } else {
                loading.value = false
                isSuccess.value = false
                ElMessage({
                    message: '3D model does not exist',
                    type: 'error',
                })
            }

        } else {
            loading.value = false
            isSuccess.value = false
            ElMessage({
                message: '3D model does not exist',
                type: 'error',
            })
        }
    }

    async function init(urlPath) {
        loading.value = true;
        emit('molstar-loading', true)
        if (plugin) {
            plugin.clear();
        } else {
            plugin = new PluginContext(MySpec);
            await plugin.init();
            const canvas = molstarCanvas.value;
            const parent = molstarParent.value;
            if (!plugin.initViewer(canvas, parent)) {
                console.error('Failed to init Mol*');
                return;
            }
        }

        const data = await plugin.builders.data.download({ url: urlPath },);
        const trajectory = await plugin.builders.structure.parseTrajectory(data, 'pdb'); //format is 'mmcif' or 'pdb' etc.
        const preset =  await plugin.builders.structure.hierarchy.applyPreset(trajectory, 'default');

        const ligandData = plugin.managers.structure.hierarchy.selection.structures[0]?.components[0]?.cell.obj?.data;
        const ligandLoci = Structure.toStructureElementLoci(ligandData as any);
        const renderer = plugin.canvas3d!.props.renderer;
        PluginCommands.Layout.Update(plugin, { 
            state: { 
                // regionState: { left: 'full' },
                showControls: true,
                isExpanded: false,
            },
        });

        plugin.dataTransaction(
            async () => {
                for (const s of plugin.managers.structure.hierarchy.selection.structures) {
                    await plugin.managers.structure.component.updateRepresentationsTheme(s.components, {
                        color: 'chain-id'
                    })
                }
            }
        )
        loading.value = false;
        emit('molstar-loading', false)
    }

    onMounted(() => {
        getPaths()
    })
</script>

<style scoped>

    #molstar-parent {
        width: 100%;
        height: 500px;
    }

    #molstar-canvas {
        width: 100%;
        height: 500px;
    }

    .container {
        width: 100%
    }

    .select {
        display: flex;
        align-items: center;
        gap: 10px; /* 间距设置 */
    }

    .select-container {
        display: flex;
        flex-direction: row;
        gap: 10px; /* 间距设置 */
        margin-bottom: 10px
    }

    .select-key {
        min-width: 100px;
    }

    @media screen and (max-width: 768px) {
        .select-container {
            width: 100%;
            display: flex;
            flex-direction: column;
            gap: 10px; /* 间距设置 */
            margin-bottom: 10px
        }

    }
</style>